﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;

namespace Gmantis.Controls.DataGrid
{
    public class DataGridColumnsHeaderPanel : RecyclingPanel
    {
        // Fields
        private DataGridColumnHeaderPresenter _indentColumnHeaderPresenter;
        private DataGridVerticalFreezingSeparatorPresenter _verticalFreezingSeparatorPresenter;
        public static readonly DependencyProperty ClipBottomMarginProperty = DependencyProperty.Register("ClipBottomMargin", typeof(double), typeof(DataGridColumnsHeaderPanel), new PropertyMetadata(0.0));
        public static readonly DependencyProperty ClipTopMarginProperty = DependencyProperty.Register("ClipTopMargin", typeof(double), typeof(DataGridColumnsHeaderPanel), new PropertyMetadata(0.0));

        // Methods
        public DataGridColumnsHeaderPanel()
        {
            this.SetCustomDefaultValues();
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            this.View.ScrollManager.Viewport = new Size(finalSize.Width, this.View.ScrollManager.Viewport.Height);
            this.Panel.RecalculateColumnsWidths();
            this.Panel.UpdateHorizontalOffset();
            double renderLeadingColumnWidth = this.View.GetRenderLeadingColumnWidth();
            double num2 = (((renderLeadingColumnWidth + this.View.ScrollManager.FrozenLeftWidth) + this.View.ScrollManager.FrozenRightWidth) + this.View.Model.VerticalFreezingSeparatorWidth) + this.View.ScrollManager.ExtentWidth;
            num2 = Math.Min(finalSize.Width, num2);
            double x = this.View.ScrollManager.FrozenLeftWidth + renderLeadingColumnWidth;
            double leftOffset = x + this.View.Model.VerticalFreezingSeparatorWidth;
            double rightOffset = num2 - this.View.ScrollManager.FrozenRightWidth;
            foreach (UIElement element in base.Children)
            {
                DataGridColumnHeaderPresenter presenter = element as DataGridColumnHeaderPresenter;
                if ((presenter != null) && !presenter.IsCollected)
                {
                    ViewColumn viewColumn = presenter.ViewColumn;
                    if (viewColumn != null)
                    {
                        double offset = renderLeadingColumnWidth + viewColumn.Offset;
                        double renderWidth = viewColumn.RenderWidth;
                        if (viewColumn.Column.IsFrozen)
                        {
                            Canvas.SetZIndex(presenter, 0x3e8);
                            presenter.Clip = null;
                        }
                        else
                        {
                            Canvas.SetZIndex(presenter, 0x3e7 - (viewColumn.Column.DisplayIndex - this.VisibleColumns.FirstVisibleItem));
                            base.ClipPresenterVertically(presenter, renderWidth, finalSize.Height, leftOffset, rightOffset, offset);
                        }
                        presenter.Arrange(new Rect(offset, 0.0, renderWidth, finalSize.Height));
                    }
                    else
                    {
                        presenter.Arrange(new Rect(0.0, 0.0, renderLeadingColumnWidth, finalSize.Height));
                    }
                }
                DataGridVerticalFreezingSeparatorPresenter presenter2 = element as DataGridVerticalFreezingSeparatorPresenter;
                if (presenter2 != null)
                {
                    presenter2.Arrange(new Rect(x, 0.0, this.View.Model.VerticalFreezingSeparatorWidth, finalSize.Height));
                }
            }
            return finalSize;
        }

        internal override void Clear()
        {
            base.Clear();
            this._verticalFreezingSeparatorPresenter = null;
            this._indentColumnHeaderPresenter = null;
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            double height;
            double columnOffset;
            this.View.ScrollManager.AvailableSize = new Size(availableSize.Width, this.View.ScrollManager.AvailableSize.Height);
            do
            {
                height = availableSize.Height;
                columnOffset = this.ValidFillParameters.ColumnOffset;
                if (!double.IsInfinity(availableSize.Width))
                {
                    double num5;
                    int columnIndex;
                    int columnDisplayIndexFromScrollPosition;
                    double num4 = Math.Max((double)0.0, (double)(availableSize.Width - this.View.GetMinFrozenWidth()));
                    FillParameters validFillParameters = this.ValidFillParameters;
                    if (validFillParameters.HorizontalDirection == GeneratorDirection.Forward)
                    {
                        double scrollPositionFromColumnDisplayIndex = this.View.ScrollManager.GetScrollPositionFromColumnDisplayIndex(validFillParameters.ColumnIndex);
                        double num8 = scrollPositionFromColumnDisplayIndex - validFillParameters.ColumnOffset;
                        columnIndex = validFillParameters.ColumnIndex;
                        columnDisplayIndexFromScrollPosition = this.View.ScrollManager.GetColumnDisplayIndexFromScrollPosition(num8 + num4, out num5);
                    }
                    else
                    {
                        double introduced20 = this.View.ScrollManager.GetScrollPositionFromColumnDisplayIndex(validFillParameters.ColumnIndex + 1);
                        double num9 = introduced20 + validFillParameters.ColumnOffset;
                        columnDisplayIndexFromScrollPosition = validFillParameters.ColumnIndex;
                        columnIndex = this.View.ScrollManager.GetColumnDisplayIndexFromScrollPosition(num9 - num4, out num5);
                    }
                    this.RemoveUnusedChildren(columnIndex, columnDisplayIndexFromScrollPosition, false);
                }
                this.VisibleColumns.ClearVisibleItems();
                if (this._indentColumnHeaderPresenter == null)
                {
                    this._indentColumnHeaderPresenter = ViewColumn.CreateIndentColumnHeaderPresenter(this.DataGrid);
                    base.Children.Add(this._indentColumnHeaderPresenter);
                }
                base.Show(this._indentColumnHeaderPresenter);
                double renderLeadingColumnWidth = this.View.GetRenderLeadingColumnWidth();
                this._indentColumnHeaderPresenter.Measure(new Size(renderLeadingColumnWidth, double.PositiveInfinity));
                columnOffset += renderLeadingColumnWidth;
                if (this.View.DataGrid.ShowLeftFreezingSeparator)
                {
                    if (this._verticalFreezingSeparatorPresenter == null)
                    {
                        this._verticalFreezingSeparatorPresenter = this.View.CreateVerticalFreezingSeparatorPresenter();
                        base.Children.Add(this._verticalFreezingSeparatorPresenter);
                    }
                    base.Show(this._verticalFreezingSeparatorPresenter);
                    this._verticalFreezingSeparatorPresenter.Measure(new Size(this.View.Model.VerticalFreezingSeparatorWidth, double.PositiveInfinity));
                    columnOffset += this.View.Model.VerticalFreezingSeparatorWidth;
                }
                else if (this._verticalFreezingSeparatorPresenter != null)
                {
                    base.Hide(this._verticalFreezingSeparatorPresenter);
                }
                foreach (ViewColumn column in this.View.GetFrozenAndScrollingColumns(this.ValidFillParameters.ColumnIndex, this.ValidFillParameters.HorizontalDirection))
                {
                    this.VisibleColumns.AddVisibleItem(column.Column);
                    DataGridColumnHeaderPresenter headerPresenter = column.GetHeaderPresenter(true);
                    if (headerPresenter != null)
                    {
                        headerPresenter.Measure(new Size(column.MeasureWidth, availableSize.Height));
                        column.DesiredWidth = Math.Max(column.DesiredWidth, headerPresenter.DesiredSize.Width);
                    }
                    columnOffset += column.MinRenderWidth;
                    if (columnOffset >= availableSize.Width)
                    {
                        break;
                    }
                }
            }
            while (!this.Panel.CheckViewPortIsFullHorizontally(columnOffset));
            this.RemoveUnusedChildren(this.VisibleColumns.FirstVisibleItem, this.VisibleColumns.LastVisibleItem, true);
            return new Size(Math.Min(availableSize.Width, columnOffset), height);
        }

        private void OnSizeChanged(object sender, SizeChangedEventArgs e)
        {
            Size newSize = e.NewSize;
            RectangleGeometry geometry = new RectangleGeometry
            {
                Rect = new Rect(0.0, -this.ClipTopMargin, newSize.Width, (newSize.Height + this.ClipTopMargin) + this.ClipBottomMargin)
            };
            base.Clip = geometry;
        }

        private void RemoveUnusedChildren(int firstVisibleColumnIndex, int lastVisibleColumnIndex, bool measureCollectedChildren)
        {
            foreach (UIElement element in new List<UIElement>(base.Children.GetTypedUIElementCollectionWrapper()))
            {
                DataGridColumnHeaderPresenter child = element as DataGridColumnHeaderPresenter;
                if (child != null)
                {
                    if (!child.IsCollected)
                    {
                        bool flag = false;
                        if (child.ViewColumn != null)
                        {
                            ViewColumn viewColumn = child.ViewColumn;
                            int columnDisplayIndex = viewColumn.ColumnDisplayIndex;
                            if ((((columnDisplayIndex < firstVisibleColumnIndex) || (columnDisplayIndex > lastVisibleColumnIndex)) && !viewColumn.Column.IsFrozen) || (viewColumn.Column.Visibility == Visibility.Collapsed))
                            {
                                flag = true;
                            }
                        }
                        if (flag)
                        {
                            this.RemoveChild(child);
                        }
                    }
                    else if (measureCollectedChildren)
                    {
                        child.Measure(new Size(0.0, 0.0));
                    }
                }
            }
        }

        private void SetCustomDefaultValues()
        {
            base.SizeChanged += new SizeChangedEventHandler(this.OnSizeChanged);
        }

        // Properties
        public double ClipBottomMargin
        {
            get
            {
                return (double)base.GetValue(ClipBottomMarginProperty);
            }
            set
            {
                base.SetValue(ClipBottomMarginProperty, value);
            }
        }

        public double ClipTopMargin
        {
            get
            {
                return (double)base.GetValue(ClipTopMarginProperty);
            }
            set
            {
                base.SetValue(ClipTopMarginProperty, value);
            }
        }

        internal DataGrid DataGrid
        {
            get
            {
                return this.View.DataGrid;
            }
        }

        internal DataGridModel Model
        {
            get
            {
                if (this.View != null)
                {
                    return this.View.Model;
                }
                return null;
            }
        }

        public DataGridRowsPanel Panel
        {
            get
            {
                return this.View.RowsPanel;
            }
        }

        private FillParameters ValidFillParameters
        {
            get
            {
                return this.View.ScrollManager.ValidFillParameters;
            }
        }

        internal DataGridView View { get; set; }

        internal DataGridVisibleItems<DataGridColumn> VisibleColumns
        {
            get
            {
                return this.View.Viewport.VisibleColumns;
            }
        }
    }
}
